# -*- coding: utf-8 -*-
"""
性能监控工具
监控API响应时间、数据库查询性能等
"""

import time
import functools
from typing import Dict, Any, Callable
from flask import request, current_app, g
import logging


class PerformanceMonitor:
    """性能监控器"""
    
    def __init__(self):
        self.metrics = {}
    
    def start_timer(self, name: str):
        """开始计时"""
        self.metrics[name] = {
            'start_time': time.time(),
            'end_time': None,
            'duration': None
        }
    
    def end_timer(self, name: str) -> float:
        """结束计时并返回持续时间"""
        if name in self.metrics:
            self.metrics[name]['end_time'] = time.time()
            self.metrics[name]['duration'] = self.metrics[name]['end_time'] - self.metrics[name]['start_time']
            return self.metrics[name]['duration']
        return 0.0
    
    def get_metrics(self) -> Dict[str, Any]:
        """获取所有指标"""
        return self.metrics.copy()
    
    def reset(self):
        """重置指标"""
        self.metrics.clear()


# 全局性能监控器
performance_monitor = PerformanceMonitor()


def monitor_performance(func_name: str = None):
    """
    性能监控装饰器
    :param func_name: 函数名称
    """
    def decorator(func: Callable) -> Callable:
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            name = func_name or func.__name__
            
            # 开始监控
            performance_monitor.start_timer(name)
            
            try:
                result = func(*args, **kwargs)
                return result
            finally:
                # 结束监控
                duration = performance_monitor.end_timer(name)
                
                # 记录性能日志
                if duration > 1.0:  # 超过1秒的请求记录警告
                    current_app.logger.warning(f"慢请求警告: {name} 耗时 {duration:.2f}秒")
                else:
                    current_app.logger.info(f"请求完成: {name} 耗时 {duration:.3f}秒")
        
        return wrapper
    return decorator


def monitor_api_performance():
    """API性能监控中间件"""
    def middleware():
        # 开始监控
        performance_monitor.start_timer('api_request')
        
        # 记录请求信息
        g.request_start_time = time.time()
        g.request_info = {
            'method': request.method,
            'path': request.path,
            'ip': request.remote_addr,
            'user_agent': request.headers.get('User-Agent', '')
        }
    
    def after_request(response):
        # 结束监控
        duration = performance_monitor.end_timer('api_request')
        
        # 记录响应信息
        g.request_duration = duration
        g.response_status = response.status_code
        
        # 记录详细的API性能日志
        log_api_performance()
        
        return response
    
    return middleware, after_request


def log_api_performance():
    """记录API性能日志"""
    if hasattr(g, 'request_duration'):
        duration = g.request_duration
        status = getattr(g, 'response_status', 200)
        method = getattr(g, 'request_info', {}).get('method', '')
        path = getattr(g, 'request_info', {}).get('path', '')
        
        # 根据响应时间分类记录
        if duration > 5.0:
            current_app.logger.error(f"极慢API: {method} {path} - {duration:.2f}s - {status}")
        elif duration > 2.0:
            current_app.logger.warning(f"慢API: {method} {path} - {duration:.2f}s - {status}")
        elif duration > 1.0:
            current_app.logger.info(f"较慢API: {method} {path} - {duration:.2f}s - {status}")
        else:
            current_app.logger.debug(f"API: {method} {path} - {duration:.3f}s - {status}")


class DatabaseMonitor:
    """数据库监控器"""
    
    def __init__(self):
        self.query_count = 0
        self.query_time = 0.0
        self.slow_queries = []
    
    def start_query(self):
        """开始查询监控"""
        self.query_count += 1
        return time.time()
    
    def end_query(self, start_time: float, query: str = None):
        """结束查询监控"""
        duration = time.time() - start_time
        self.query_time += duration
        
        # 记录慢查询
        if duration > 0.1:  # 超过100ms的查询
            self.slow_queries.append({
                'query': query,
                'duration': duration,
                'timestamp': time.time()
            })
            
            if duration > 1.0:  # 超过1秒的查询记录错误
                current_app.logger.error(f"慢查询警告: {duration:.2f}s - {query}")
    
    def get_stats(self) -> Dict[str, Any]:
        """获取数据库统计信息"""
        return {
            'query_count': self.query_count,
            'total_time': self.query_time,
            'avg_time': self.query_time / self.query_count if self.query_count > 0 else 0,
            'slow_queries_count': len(self.slow_queries)
        }
    
    def reset(self):
        """重置统计"""
        self.query_count = 0
        self.query_time = 0.0
        self.slow_queries.clear()


# 全局数据库监控器
db_monitor = DatabaseMonitor()


def monitor_db_query(func: Callable) -> Callable:
    """数据库查询监控装饰器"""
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        start_time = db_monitor.start_query()
        
        try:
            result = func(*args, **kwargs)
            return result
        finally:
            db_monitor.end_query(start_time, str(func.__name__))
    
    return wrapper


class MemoryMonitor:
    """内存监控器"""
    
    @staticmethod
    def get_memory_usage() -> Dict[str, Any]:
        """获取内存使用情况"""
        try:
            import psutil
            process = psutil.Process()
            memory_info = process.memory_info()
            
            return {
                'rss': memory_info.rss,  # 物理内存
                'vms': memory_info.vms,  # 虚拟内存
                'percent': process.memory_percent(),
                'available': psutil.virtual_memory().available
            }
        except ImportError:
            return {'error': 'psutil not installed'}
    
    @staticmethod
    def log_memory_usage():
        """记录内存使用情况"""
        memory_info = MemoryMonitor.get_memory_usage()
        if 'error' not in memory_info:
            current_app.logger.info(
                f"内存使用: RSS={memory_info['rss']/1024/1024:.1f}MB, "
                f"VMS={memory_info['vms']/1024/1024:.1f}MB, "
                f"使用率={memory_info['percent']:.1f}%"
            )


def setup_performance_monitoring(app):
    """设置性能监控"""
    # 注册中间件
    middleware, after_request = monitor_api_performance()
    app.before_request(middleware)
    app.after_request(after_request)
    
    # 设置定时任务记录内存使用
    @app.before_request
    def log_memory_before_request():
        if app.config.get('LOG_MEMORY_USAGE', False):
            MemoryMonitor.log_memory_usage()
    
    # 添加性能监控端点
    @app.route('/api/v1/monitor/performance')
    def get_performance_metrics():
        """获取性能指标"""
        return {
            'api_metrics': performance_monitor.get_metrics(),
            'db_metrics': db_monitor.get_stats(),
            'memory_metrics': MemoryMonitor.get_memory_usage()
        } 